﻿using System;
using System.Collections.Generic;
using System.Configuration;
using Core.DataAccess.Tools.Interfaces;
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Tool.hbm2ddl;

namespace Core.DataAccess.Tools.Implementations
{

    //Setting up connection between orm and database
    public class SessionFactoryManager:ISessionFactoryManager
    {
        public string ConnectionString { get; set; }
        internal FluentConfiguration Configuration { get; set; }


        public SessionFactoryManager()
        {
            ConnectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
        }


        public ISessionFactory GetSessionFactory()
        {
            var model = AutoMap.AssemblyOf<Model.User>().Conventions.Add<CascadeConvention>()
                .UseOverridesFromAssemblyOf<Core.DataAccess.Tools.Implementations.OverrideMappings.UserMapping>();
            SetUpConnection(new List<AutoPersistenceModel>() { model });

            var sessionFactory = SetUpDatabaseConnection(new List<AutoPersistenceModel>() {model})
                .BuildSessionFactory();

            return sessionFactory;
        }


        private FluentConfiguration SetUpDatabaseConnection(IEnumerable<AutoPersistenceModel> models)
        {
            return UpdateConfiguration(Configuration);
        }

        private void SetUpConnection(IEnumerable<AutoPersistenceModel> models)
        {
            Configuration = Fluently.Configure()
                    .Database(MsSqlConfiguration
                    .MsSql2008.ConnectionString(ConnectionString)
                    .ShowSql());

            foreach (var autoPersistenceModel in models)
            {
                Configuration.Mappings(x => x.AutoMappings.Add(autoPersistenceModel));
            }
        }

        private FluentConfiguration UpdateConfiguration(FluentConfiguration configuration)
        {
                return configuration.ExposeConfiguration(cfg => new SchemaUpdate(cfg));
        }

        internal FluentConfiguration CreateConfiguration(FluentConfiguration configuration)
        {
            return configuration.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(false,true));
        }
    }
}
